package NeiBuLei;

/*
* 依赖外部类对象:成员内部类,方法内部类,匿名内部类
* 不依赖外部类对象:静态内部类, 所以做项目优先考虑静态内部类(它不会造成内存泄漏)
*别的内部类要引用外部类对象时,如果内部类生命周期太长了,会强制不让外部类去释放对象,
* 会导致可能程序关闭了,但是外部类的对象还没有释放导致占用内存,  这就是内存泄漏
* */
public class Nbl {
    public static void main(String[] args) {
       Outer outer = new Outer();
       outer.print();  //成员内部类
       outer.shift(); //方法内部类

       Outer.Inner3 inner3 = new Outer.Inner3();
       inner3.print();  //静态内部类

       outer.ExtendsNiMing();//继承式匿名内部类
       outer.ImplementsNiMing();//接口式匿名内部类
        //参数式匿名内部类
       outer.CanShuNiMing(new Cat() {
           public void eat() {
               System.out.println("参数式匿名内部类");
           }
       });
    }
}
class Outer{
    //------------成员内部类------------
    //建议使用封装方法来new 内部类去调用内部类里面的方法
    public void print(){
        Inner inner = new Inner();
        inner.show();
    }

    class Inner{
        private String name = "inner";
        public void show(){
            System.out.println("成员内部类"+name);
        }
    }
    //------------方法内部类-------------
    //show方法的局部变量或方法的参数，实际必须是常量
    public void shift(/*final int i*/){
        /*final*/ int i = 10 ;
        class Inner2{
             public void printI(){
                 //i++；从内部类引用的本地变量必须是最终变量，或实际上的最终变量
                 System.out.println(i);
             }
        }
        Inner2 inner2 = new Inner2();
        inner2.printI();
    }

    //-----------静态内部类------------
    /* 静态内部类,在类中定义一个带有静态修饰符的内部类
    静态的含义是该内部类可以向其他静态成员一样,在没有外部类的对象时,也能够访问到它
    静态嵌套类仅能访问外部类的静态成员和方法
    */
    static class Inner3{
        //静态内部类只能访问外部静态变量 ，唯一作用只能用作封装
        public void print(){
            System.out.println("静态内部类");
        }
    }
    //-----------匿名内部类--------------
    /*1.继承式匿名内部类
    * 2.接口式匿名内部类
    * 3.参数式匿名内部类
    * (1)不能有构造方法,只能有一个实例.   一次性使用建议用
    * (2)不能定义任何静态成员和静态方法
    * (3)不能是public,private,protected,static
    * (4)一定是在new的后面,用其隐含实现一个接口或继承并实现一个类
    * (5)匿名内部类为局部的,所有局部内部类的所有限制都对其生效
    * */
    //继承式
     public void ExtendsNiMing(){
   int B = 1; //外部方法中的变量在内部类中也充当final常量，因为内部类生命周期可能比外部类长
          Cat cat = new Cat() {
              int a = B+2;  // 可以调用外部方法变量，但不能修改
              int c = ++A;  //此处的A为外部类对象的成员变量，内部类可以访问到并修改A的值，但是不能直接给A赋值
//              A = 2 ;此处编译错误
              public void eat() {
              //    B++; 此处B不能改变，因为为final
                  A++;//外部类对象的成员变量，可以被访问
                  System.out.println("猫,继承式匿名内部类"+A);
              }
          };
          cat.eat();
     }
     //接口式
    public void ImplementsNiMing(){
         Dog dog = new Dog() {
             public void run() {
                 System.out.println("狗跑,接口式匿名内部类");
             }
         };
         dog.run();
    }
    //参数式
    public void CanShuNiMing(Cat cat){
         cat.eat();
    }



}
abstract class Cat{
    int A = 0;
    abstract public void eat();
}
interface  Dog{
    public void run();
}